package org.h2.server.web;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.h2.server.web.PageParser;
import org.h2.server.web.WebServer;
import org.h2.tools.Server;
import org.h2.util.StringUtils;

import com.fzy.core.utils.U;

public class WebServlet extends HttpServlet {

	private static final long serialVersionUID = 1542936785794131015L;
//	private Connection conn;
    private transient WebServer server;
    private Server tcp;

    public void init() throws ServletException {
        String baseDir = U.getAppPath() + "h2";
        
        try {
            org.h2.Driver.load();

//            // This will get the setting from a context-param in web.xml if defined:
//            ServletContext servletContext = getServletContext();
//            String url = "jdbc:h2:./test";
//            String user = "sa";
//            String password = "";
//
//            conn = DriverManager.getConnection(url, user, password);
//            servletContext.setAttribute("connection", conn);

            // Start the server if configured to do so
            String serverParams = "-tcpAllowOthers -baseDir " + baseDir;
            if (serverParams != null) {
                String[] params = StringUtils.arraySplit(serverParams, ' ', true);
                tcp = Server.createTcpServer(params);
                tcp.start();
            }
            // To access the database in server mode, use the database URL:
            // jdbc:h2:tcp://localhost/~/test

        } catch (Exception e) {
            e.printStackTrace();
        }
    	
    	
        ServletConfig config = getServletConfig();
        Enumeration en = config.getInitParameterNames();
        ArrayList list = new ArrayList();
        while (en.hasMoreElements()) {
            String name = en.nextElement().toString();
            String value = config.getInitParameter(name);
            if (!name.startsWith("-")) {
                name = "-" + name;
            }
            list.add(name);
            if (value.length() > 0) {
                list.add(value);
            }
        }
        //add base directory
        list.add("-baseDir");
        list.add(baseDir);
//        list.add("-tcp");
//        list.add("-tcpAllowOthers");
        list.add("-webAllowOthers");
//        list.add("-trace");
        
        String[] args = new String[list.size()];
        list.toArray(args);
        server = new WebServer();
        server.init(args);
    }

    public void destroy() {
        if (tcp != null) {
        	tcp.stop();
        	tcp = null;
        }
//        try {
//            conn.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
		super.destroy();
	}



	private boolean allow(HttpServletRequest req) {
        if (server.getAllowOthers()) {
            return true;
        }
        String addr = req.getRemoteAddr();
        try {
            InetAddress address = InetAddress.getByName(addr);
            return address.isLoopbackAddress();
        } catch (UnknownHostException e) {
            return false;
        }
    }

    private String getAllowedFile(HttpServletRequest req, String requestedFile) {
        if (!allow(req)) {
            return "notAllowed.jsp";
        }
        if (requestedFile.length() == 0) {
            return "index.do";
        }
        return requestedFile;
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String file = req.getPathInfo();
        if (file == null) {
            resp.sendRedirect(req.getRequestURI() + "/");
            return;
        } else if (file.startsWith("/")) {
            file = file.substring(1);
        }
        file = getAllowedFile(req, file);
        byte[] bytes = null;
        Properties attributes = new Properties();
        Enumeration en = req.getAttributeNames();
        while (en.hasMoreElements()) {
            String name = en.nextElement().toString();
            String value = req.getAttribute(name).toString();
            attributes.put(name, value);
        }
        en = req.getParameterNames();
        while (en.hasMoreElements()) {
            String name = en.nextElement().toString();
            String value = req.getParameter(name);
            attributes.put(name, value);
        }
        WebSession session = null;
        String sessionId = attributes.getProperty("jsessionid");
        if (sessionId != null) {
            session = server.getSession(sessionId);
        }
        WebThread app = new WebThread(null, server);
        app.setSession(session, attributes);
        String ifModifiedSince = req.getHeader("if-modified-since");

        String hostAddr = req.getRemoteAddr();
        file = app.processRequest(file, hostAddr);
        session = app.getSession();

        String mimeType = app.getMimeType();
        boolean cache = app.getCache();

        if (cache && server.getStartDateTime().equals(ifModifiedSince)) {
            resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            return;
        }
        bytes = server.getFile(file);
        if (bytes == null) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            try {
                bytes = StringUtils.utf8Encode("File not found: " + file);
            } catch (SQLException e) {
                server.traceError(e);
            }
        } else {
            if (session != null && file.endsWith(".jsp")) {
                String page = StringUtils.utf8Decode(bytes);
                page = PageParser.parse(page, session.map);
                try {
                    bytes = StringUtils.utf8Encode(page);
                } catch (SQLException e) {
                    server.traceError(e);
                }
            }
            resp.setContentType(mimeType);
            if (!cache) {
                resp.setHeader("Cache-Control", "no-cache");
            } else {
                resp.setHeader("Cache-Control", "max-age=10");
                resp.setHeader("Last-Modified", server.getStartDateTime());
            }
        }
        if (bytes != null) {
            ServletOutputStream out = resp.getOutputStream();
            out.write(bytes);
        }
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doGet(req, resp);
    }
}
